// src/utils/http.ts

import { useMemberStore, useStore } from '@/stores'
import type { SceneValue } from '@/types/global'
import type { IOrderItem } from '@/types/order'
const { getStoreInfo } = useStore()

const accessTokenKip = (url: string) => {
  const urls = [
    '/sys/webchat/dict/all',
    '/sys/webchat/categories/list',
    '/sys/webchat/categories/gooddetail',
    '/sys/webchat/categories/searchGoods',
    '/sys/webchat/categories/banner/list',
    '/sys/webchat/categories/taglist',
    '/sys/webchat/cart',
    '/sys/webchat/cart/list',
    '/sys/webchat/cart/page',
    'sys/app/store/appPage',
  ]
  return urls.some((v) => url.includes(v))
}

// 请求基地址
const baseURL = 'http://localhost:7070'
// const baseURL = 'http://v33882ab.natappfree.cc'
// const baseURL = 'https://pcapi-xiaotuxian-front-devtest.itheima.net'

// 拦截器配置
const httpInterceptor = {
  // 拦截前触发
  invoke(options: UniApp.RequestOptions) {
    options.timeout = 10000
    const storeId = getStoreInfo()?.storeId
    options.header = {
      platform: 'wechat',
      ...(storeId && { storeId }),
      tenantId: '1904755736660021249', // 1904755736660021249
      ...options.header,
    }
    // 4. 添加 token 请求头标识
    const memberStore = useMemberStore()
    const access_token = memberStore.profile?.access_token

    if (!accessTokenKip(options.url)) {
      if (access_token) {
        options.header['Authorization'] = 'Bearer ' + access_token
      }
    }

    // 1. 非 http 开头需拼接地址
    if (!options.url.startsWith('http')) {
      options.url = baseURL + options.url
    }
  },
}

// 拦截 request 请求
uni.addInterceptor('request', httpInterceptor)
// 拦截 uploadFile 文件上传
uni.addInterceptor('uploadFile', httpInterceptor)

/**
 * 请求函数
 * @param  UniApp.RequestOptions
 * @returns Promise
 *  1. 返回 Promise 对象，用于处理返回值类型
 *  2. 获取数据成功
 *    2.1 提取核心数据 res.data
 *    2.2 添加类型，支持泛型
 *  3. 获取数据失败
 *    3.1 401错误  -> 清理用户信息，跳转到登录页
 *    3.2 其他错误 -> 根据后端错误信息轻提示
 *    3.3 网络错误 -> 提示用户换网络
 */
type Data<T> = {
  code: string
  message: string
  data: T
}
// 2.2 添加类型，支持泛型
export const http = <T>(options: UniApp.RequestOptions) => {
  // 1. 返回 Promise 对象
  return new Promise<Data<T>>((resolve, reject) => {
    uni.request({
      ...options,
      // 响应成功
      success(res: any) {
        // 状态码 2xx，参考 axios 的设计
        if (res.statusCode >= 200 && res.statusCode < 300) {
          // 2.1 提取核心数据 res.data
          if (res.data.code === 401) {
            // 401错误  -> 清理用户信息，跳转到登录页
            const memberStore = useMemberStore()
            memberStore.clearProfile()
            uni.navigateTo({ url: '/pages/login/login' })
            reject(res)
          } else {
            resolve(res.data as Data<T>)
          }
        } else if (res.statusCode === 401) {
          // 401错误  -> 清理用户信息，跳转到登录页
          const memberStore = useMemberStore()
          memberStore.clearProfile()
          uni.navigateTo({ url: '/pages/login/login' })
          reject(res)
        } else {
          // 其他错误 -> 根据后端错误信息轻提示
          uni.showToast({
            icon: 'none',
            title: (res.data as Data<T>).message || '请求错误',
          })
          reject(res)
        }
      },
      // 响应失败
      fail(err) {
        uni.showToast({
          icon: 'none',
          title: '网络错误，换个网络试试',
        })
        reject(err)
      },
    })
  })
}

export const parseQueryString = (queryString: string) => {
  const params: any = {}
  const queries = queryString.replace(/^\?/, '').split('&')

  for (let i = 0; i < queries.length; i++) {
    const [key, value] = queries[i].split('=')
    if (key.length > 0) {
      params[decodeURIComponent(key)] = decodeURIComponent(value || '')
    }
  }

  return params
}

// 配送天
export const deliveryTimeMultiDateArray = () => {
  const days = ['今天', '明天', '后天']
  const today = new Date()
  const dates = []
  for (let i = 0; i < 5; i++) {
    const date = new Date(today)
    date.setDate(today.getDate() + i)
    const label =
      i < 3
        ? `${date.getMonth() + 1}月${date.getDate()}日（${days[i]}）`
        : `${date.getMonth() + 1}月${date.getDate()}日`
    dates.push(label)
  }
  return dates
}

// 配送时
export const deliveryTimeMultiHourArray = (num: any) => {
  const now = new Date()
  const currentHour = now.getHours()

  // 生成小时数组，仅适用于今天
  let startHour = 8
  let endHour = 23
  if (num !== null && num === 0) {
    startHour = currentHour
    endHour = 23
  }

  const hours = Array.from(
    { length: endHour - startHour + 1 },
    (_, i) => `${String(startHour + i).padStart(2, '0')}时`,
  )
  return hours
}

// 配送分
export const deliveryTimeMultiMinutsArray = (num: any) => {
  const now = new Date()
  const currentHour = now.getHours()
  const currentMinute = now.getMinutes()

  // 生成小时数组，仅适用于今天
  let startHour = 8
  let endHour = 23
  if (num !== null && num === 0) {
    // 假设用户选择的是今天
    startHour = currentHour
    endHour = 23
  }

  // 生成分钟数组，仅适用于今天且小时等于当前小时
  let startMinute = 0
  if (num !== null && num === 0 && startHour === currentHour) {
    // 向上取整到下一个5分钟
    startMinute = Math.ceil(currentMinute / 5) * 5
    if (startMinute >= 60) {
      startMinute = 0 // 如果分钟是60，则重置为0，并进位到小时
    }
  }
  const minutes = Array.from({ length: (60 - startMinute) / 5 }, (_, i) => {
    const min = startMinute + i * 5
    return `${String(min).padStart(2, '0')}分`
  })

  return minutes
}

export const formatChineseJson = (jsonStr: string) => {
  try {
    const obj = JSON.parse(jsonStr)
    return Object.entries(obj)
      .map(([key, value]) => `${key}: ${value}`)
      .join(', ')
  } catch (e) {
    return '无效的 JSON 字符串'
  }
}

export const getOrCreateUUID = (storageKey = 'APP_DEVICE_UUID') => {
  try {
    // 尝试从本地存储中获取已有的 UUID
    const existingUUID = uni.getStorageSync(storageKey)
    if (existingUUID) {
      return existingUUID
    }

    // 如果没有，生成一个新的 UUID v4
    const newUUID = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      const r = (Math.random() * 16) | 0
      const v = c === 'x' ? r : (r & 0x3) | 0x8
      return v.toString(16)
    })

    // 保存到本地存储，下次可以直接获取
    uni.setStorageSync(storageKey, newUUID)

    return newUUID
  } catch (e) {
    console.error('获取或生成 UUID 失败', e)
    return null
  }
}

export const parseCustomDateTime = (input: string) => {
  // 提取日期和时间部分
  const datePart = input.match(/(\d{1,2})月(\d{1,2})日/)
  const timePart = input.match(/(\d{1,2})时(\d{1,2})分/)
  if (!datePart || !timePart) {
    throw new Error('Invalid date or time format')
  }

  const month = parseInt(datePart[1], 10)
  const day = parseInt(datePart[2], 10)
  const hours = parseInt(timePart[1], 10)
  const minutes = parseInt(timePart[2], 10)
  const year = new Date().getFullYear()
  return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':00'
}

export const formateStr = (item: IOrderItem) => {
  if (item.isSetmeal === 1) {
    return item.description
  }
  if (!item.hasSku) {
    return item.description
  }
  if (!item.specification) {
    return ''
  } else if ('{}' === item.specification) {
    return ''
  } else {
    return formatChineseJson(item.specification)
  }
}
// 封装一个工具函数
export const getDistance = (lat1: number, lng1: number, lat2: number, lng2: number) => {
  const rad = (d: number) => (d * Math.PI) / 180.0
  const EARTH_RADIUS = 6378.137
  const x = (rad(lng1) - rad(lng2)) * Math.cos(rad((lat1 + lat2) / 2))
  const y = rad(lat1) - rad(lat2)
  const d = Math.sqrt(x * x + y * y) * EARTH_RADIUS
  return d * 1000 // 返回米
}
/**
 * 计算两个经纬度之间的直线距离（单位：米）
 * @param {Number} lat1 起点纬度
 * @param {Number} lng1 起点经度
 * @param {Number} lat2 终点纬度
 * @param {Number} lng2 终点经度
 * @returns {Number} 距离（米）
 * distance1 = calculateDistance(38.40488843, 112.74651565, 38.4066483, 112.74612468)
 */
export const calculateDistance = (lat1: number, lng1: number, lat2: number, lng2: number) => {
  const EARTH_RADIUS = 6378.137 // 地球半径（km）

  const rad = (degree: number) => (degree * Math.PI) / 180.0

  const radLat1 = rad(lat1)
  const radLat2 = rad(lat2)
  const a = radLat1 - radLat2
  const b = rad(lng1) - rad(lng2)

  let s =
    2 *
    Math.asin(
      Math.sqrt(
        Math.pow(Math.sin(a / 2), 2) +
          Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2),
      ),
    )
  s = s * EARTH_RADIUS
  s = Math.round(s * 10000) / 10 // 转换为米，保留一位小数
  return s
}

/**
 * 获取日期范围
 * @param option
 * @returns
 */
export const getDateRange = (option: any) => {
  const today = new Date()
  today.setHours(0, 0, 0, 0) // 清空时分秒，只保留日期

  let start,
    end = new Date(today)

  switch (option) {
    case '最近10天':
      start = new Date(today)
      start.setDate(today.getDate() - 10)
      break
    case '最近30天':
      start = new Date(today)
      start.setDate(today.getDate() - 30)
      break
    case '最近60天':
      start = new Date(today)
      start.setDate(today.getDate() - 60)
      break
    case '最近90天':
      start = new Date(today)
      start.setDate(today.getDate() - 90)
      break
    case '本月':
      start = new Date(today.getFullYear(), today.getMonth(), 1)
      break
    case '上月':
      start = new Date(today.getFullYear(), today.getMonth() - 1, 1)
      end = new Date(today.getFullYear(), today.getMonth(), 0) // 上月最后一天
      break
    default:
      start = new Date(today)
  }
  return { start, end }
}
// 格式化日期为 YYYY-MM-DD
export const formatDate = (date: any) => {
  if (!date) return ''
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  return `${year}-${month}-${day}`
}
export const getStartDateAndEndStr = (dateRangeOptionVal: string) => {
  return {
    startDate: `${formatDate(getDateRange(dateRangeOptionVal).start)} 00:00:00`,
    endDate: `${formatDate(getDateRange(dateRangeOptionVal).end)} 23:59:59`,
  }
}

/**
 * 修复 uni.uploadFile 返回的乱码响应体
 * @param {string} str - 原始响应字符串
 * @returns {string} 修复后的字符串
 */
export const fixResponseEncoding = (str: any) => {
  // 如果已经是正常中文，直接返回
  if (typeof str !== 'string' || /[\u4e00-\u9fa5]/.test(str)) {
    return str
  }

  try {
    // 方法：先按字节重建 Uint8Array，再用 UTF-8 解码
    const uint8Array = new Uint8Array(str.length)
    for (let i = 0; i < str.length; i++) {
      uint8Array[i] = str.charCodeAt(i) & 0xff
    }
    return new TextDecoder('utf-8').decode(uint8Array)
  } catch (e) {
    // 兜底方案
    const fallbackFix = (str: any) => {
      try {
        return decodeURIComponent(encodeURIComponent(str))
      } catch {
        return str
      }
    }
    return fallbackFix(str)
  }
}

/**
 * 兜底修复方法（适用于不支持 TextDecoder 的环境）
 */
